/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @addtogroup IotHardware
 * @{
 *
 * @brief Provides APIs for operating devices,
 * including flash, GPIO, I2C, PWM, UART, and watchdog APIs.
 *
 *
 *
 * @since 2.2
 * @version 2.2
 */
#include "iot_errno.h"
#include "driver/chip/hal_pwm.h"

//#define PWM_OUTPUT_CHL        PWM_GROUP0_CH0
#define PWM_OUTPUT_MODE PWM_CYCLE_MODE

/**
 * @brief Initializes a PWM device.
 *
 * @param port Indicates the port number of the PWM device.
 * @return Returns {@link IOT_SUCCESS} if the PWM device is initialized;
 * returns {@link IOT_FAILURE} otherwise. For details about other return values, see the chip description.
 * @since 2.2
 * @version 2.2
 */
unsigned int IoTPwmInit(unsigned int port)
{
    HAL_Status status = HAL_ERROR;
    PWM_ClkParam clk_param;

    if ((PWM_CH_ID)port >= PWM_CH_NUM) {
        printf("IoTPwmInit port=%u error\r\n", port);
        return IOT_FAILURE;
    }

    clk_param.clk = PWM_CLK_HOSC;
    clk_param.div = PWM_SRC_CLK_DIV_1;
    status = HAL_PWM_GroupClkCfg((PWM_CH_ID)port / 2, &clk_param);
    if (status != HAL_OK) {
        printf("IoTPwmInit ClkCfg port=%u error\r\n", port);
        return IOT_FAILURE;
    }

    return IOT_SUCCESS;
}

/**
 * @brief Deinitializes a PWM device.
 *
 * @param port Indicates the port number of the PWM device.
 * @return Returns {@link IOT_SUCCESS} if the PWM device is deinitialized;
 * returns {@link IOT_FAILURE} otherwise. For details about other return values, see the chip description.
 * @since 2.2
 * @version 2.2
 */
unsigned int IoTPwmDeinit(unsigned int port)
{
    if ((PWM_CH_ID)port >= PWM_CH_NUM) {
        printf("IoTPwmDeinit port=%u error\r\n", port);
        return IOT_FAILURE;
    }

    HAL_PWM_EnableCh((PWM_CH_ID)port, PWM_OUTPUT_MODE, 0);
    HAL_PWM_ChDeinit((PWM_CH_ID)port);

    return IOT_SUCCESS;
}

/**
 * @brief Starts PWM signal output from a specified port based on the given output frequency and duty cycle.
 *
 *
 *
 * @param port Indicates the port number of the PWM device.
 * @param duty Indicates the duty cycle for PWM signal output. The value ranges from 1 to 99.
 * @param freq Indicates the frequency for PWM signal output.
 * @return Returns {@link IOT_SUCCESS} if the PWM signal output is started;
 * returns {@link IOT_FAILURE} otherwise. For details about other return values, see the chip description.
 * @since 2.2
 * @version 2.2
 */
unsigned int IoTPwmStart(unsigned int port, unsigned short duty,
             unsigned int freq)
{
    HAL_Status status = HAL_ERROR;
    PWM_ChInitParam ch_param;
    int max_duty_ratio = 0;

    if (((PWM_CH_ID)port >= PWM_CH_NUM) || (duty > 99)) {
        printf("IoTPwmStart error\r\n");
        return IOT_FAILURE;
    }

    ch_param.hz = freq;
    ch_param.mode = PWM_OUTPUT_MODE;
    ch_param.polarity = PWM_HIGHLEVE;
    max_duty_ratio = HAL_PWM_ChInit((PWM_CH_ID)port, &ch_param);
    if (max_duty_ratio == -1) {
        printf("HAL_PWM_ChInit error\r\n");
        return IOT_FAILURE;
    }
    printf("max_duty_ratio = %d\r\n", max_duty_ratio);

    status = HAL_PWM_ChSetDutyRatio((PWM_CH_ID)port,
                    max_duty_ratio * duty / 100);
    if (status != HAL_OK) {
        printf("HAL_PWM_ChSetDutyRatio error\r\n");
        return IOT_FAILURE;
    }

    status = HAL_PWM_EnableCh((PWM_CH_ID)port, PWM_OUTPUT_MODE, 1);
    if (status != HAL_OK) {
        printf("HAL_PWM_EnableCh error\r\n");
        return IOT_FAILURE;
    }

    return IOT_SUCCESS;
}

/**
 * @brief Stops PWM signal output from a specified port.
 *
 * @param port Indicates the port number of the PWM device.
 * @return Returns {@link IOT_SUCCESS} if the PWM signal output is stopped;
 * returns {@link IOT_FAILURE} otherwise. For details about other return values, see the chip description.
 * @since 2.2
 * @version 2.2
 */
unsigned int IoTPwmStop(unsigned int port)
{
    HAL_Status status = HAL_ERROR;

    if ((PWM_CH_ID)port >= PWM_CH_NUM) {
        printf("IoTPwmStop port=%u error\r\n", port);
        return IOT_FAILURE;
    }

    status = HAL_PWM_EnableCh((PWM_CH_ID)port, PWM_OUTPUT_MODE, 0);
    if (status != HAL_OK) {
        printf("IoTPwmStop disable port=%u error\r\n", port);
        return IOT_FAILURE;
    }

    return IOT_SUCCESS;
}

/** @} */
